// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#ifndef MGCQUATERNION_H
#define MGCQUATERNION_H

#include "MgcMatrix3.h"


class MgcQuaternion
{
public:
    MgcReal w, x, y, z;

    // construction and destruction
    MgcQuaternion (MgcReal fW = 1.0, MgcReal fX = 0.0, MgcReal fY = 0.0,
        MgcReal fZ = 0.0);
    MgcQuaternion (const MgcQuaternion& rkQ);

    // conversion between quaternions, matrices, and angle-axes
    void FromRotationMatrix (const MgcMatrix3& kRot);
    void ToRotationMatrix (MgcMatrix3& kRot) const;
    void FromAngleAxis (const MgcReal& rfAngle, const MgcVector3& rkAxis);
    void ToAngleAxis (MgcReal& rfAngle, MgcVector3& rkAxis) const;
    void FromAxes (const MgcVector3* akAxis);
    void ToAxes (MgcVector3* akAxis) const;

    // arithmetic operations
    MgcQuaternion& operator= (const MgcQuaternion& rkQ);
    MgcQuaternion operator+ (const MgcQuaternion& rkQ) const;
    MgcQuaternion operator- (const MgcQuaternion& rkQ) const;
    MgcQuaternion operator* (const MgcQuaternion& rkQ) const;
    MgcQuaternion operator* (MgcReal fScalar) const;
    friend MgcQuaternion operator* (MgcReal fScalar,
        const MgcQuaternion& rkQ);
    MgcQuaternion operator- () const;

    // functions of a quaternion
    MgcReal Dot (const MgcQuaternion& rkQ) const;  // dot product
    MgcReal Norm () const;  // squared-length
    MgcQuaternion Inverse () const;  // apply to non-zero quaternion
    MgcQuaternion UnitInverse () const;  // apply to unit-length quaternion
    MgcQuaternion Exp () const;
    MgcQuaternion Log () const;

    // rotation of a vector by a quaternion
    MgcVector3 operator* (const MgcVector3& rkVector) const;

    // spherical linear interpolation
    static MgcQuaternion Slerp (MgcReal fT, const MgcQuaternion& rkP,
        const MgcQuaternion& rkQ);

    static MgcQuaternion SlerpExtraSpins (MgcReal fT,
        const MgcQuaternion& rkP, const MgcQuaternion& rkQ,
        int iExtraSpins);

    // setup for spherical quadratic interpolation
    static void Intermediate (const MgcQuaternion& rkQ0,
        const MgcQuaternion& rkQ1, const MgcQuaternion& rkQ2,
        MgcQuaternion& rka, MgcQuaternion& rkB);

    // spherical quadratic interpolation
    static MgcQuaternion Squad (MgcReal fT, const MgcQuaternion& rkP,
        const MgcQuaternion& rkA, const MgcQuaternion& rkB,
        const MgcQuaternion& rkQ);

    // cutoff for sine near zero
    static MgcReal ms_fEpsilon;

    // special values
    static MgcQuaternion ZERO;
    static MgcQuaternion IDENTITY;
};

#endif
